package com.kkks.spring_rest.tick.dao.impl;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.stereotype.Repository;
//import org.springframework.transaction.annotation.Propagation;
//import org.springframework.transaction.annotation.Transactional;

import com.kkks.spring_rest.tick.dao.HibernateTemplateBaseDao;

@Repository("hibernateTemplateBaseDao")
public class HibernateTemplateBaseDaoImpl<T, ID extends Serializable>
		implements HibernateTemplateBaseDao<T> {

	@Autowired
	private HibernateTemplate hibernateTemplate;

	private static final Logger logger = Logger
			.getLogger(HibernateTemplateBaseDaoImpl.class);

	public HibernateTemplate getHibernateTemplate() {
		return hibernateTemplate;
	}

	public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
		this.hibernateTemplate = hibernateTemplate;
	}

	/**
	 * 描述 通过 id 主键查询对象实体
	 * 
	 * @param id
	 * @return 实体类
	 */
	@Override
//	@Transactional(propagation = Propagation.REQUIRED, readOnly = true)
	public T findById(Class<T> entityClass, Serializable id) {// TODO
		try {
			if (logger.isDebugEnabled()) {
				logger.debug("开始查找ID为" + id + "的实体：" + entityClass.getName());
			}
			return (T) this.getHibernateTemplate().get(entityClass, id);
		} catch (RuntimeException e) {
			logger.error("查找指定ID实体异常，ID：" + id, e);
			throw e;
		}
	}

	/**
	 * 描述 多条件查询实体对象
	 * 
	 * @param hql
	 * @param values
	 * @return 实体类
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
//	@Transactional(propagation = Propagation.REQUIRED, readOnly = true)
	public T findTByHql(final String hql, final Object... values) {// TODO
		try {
			if (logger.isDebugEnabled()) {
				logger.debug("开始通过hql 查找实体类 : " + hql);
			}
			return (T) this.getHibernateTemplate().execute(
					new HibernateCallback() {
						@Override
						public Object doInHibernate(Session session)
								throws HibernateException, SQLException {
							Query query = session.createQuery(hql);
							if (values != null) {
								for (int i = 0; i < values.length; i++) {
									query.setParameter(i, values[i]);
								}
							}
							return query.setMaxResults(1).uniqueResult();
						}
					});
		} catch (RuntimeException e) {
			logger.error("开始通过hql 查找实体类异常：" + e);
			throw e;
		}
	}

	/**
	 * 描述 获取所有实体集合
	 * 
	 * @param entityClass
	 * @return List<T> 集合
	 */
	@SuppressWarnings("unchecked")
	@Override
//	@Transactional(propagation = Propagation.REQUIRED, readOnly = true)
	public List<T> findAll(Class<T> entityClass) {// TODO Auto-generated method
		try {
			if (logger.isDebugEnabled()) {
				logger.debug("开始查找指定实体集合：" + entityClass.getName());
			}
			return this.getHibernateTemplate().find(
					"from " + entityClass.getName());
		} catch (RuntimeException e) {
			logger.error("查找指定实体集合异常，实体：" + entityClass.getName(), e);
			throw e;
		}
	}

	/**
	 * 描述 获取所有实体集合分页方法
	 * 
	 * @param hql
	 * @param firstResult
	 * @param length
	 * @return List<T>
	 */
	@SuppressWarnings("unchecked")
//	@Transactional(propagation = Propagation.REQUIRED, readOnly = true)
	public List<T> findPaginationAllList(final String hql,
			final int firstResult, final int length) {// TODO
		List<T> result = new ArrayList<T>();
		try {
			result = getHibernateTemplate().executeFind(
					new HibernateCallback<T>() {
						@Override
						public T doInHibernate(Session session)
								throws HibernateException, SQLException {
							Query q = session.createQuery(hql);
							q.setFirstResult(firstResult);
							q.setMaxResults(length);
							List<T> list = q.list();
							logger.info("取到的每页的size" + list.size());
							return (T) list;
						}
					});
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * 描述 通过 hql语句 ，参数值 查询实体集合
	 * 
	 * @param hql
	 * @param values
	 * @return List<T> 集合
	 */
	@SuppressWarnings("unchecked")
	@Override
//	@Transactional(propagation = Propagation.REQUIRED, readOnly = true)
	public List<T> findListByHql(String hql, Object... values) {// TODO
		try {
			if (logger.isDebugEnabled()) {
				logger.debug("开始查询指定HQL语句, " + hql);
			}
			return this.getHibernateTemplate().find(hql, values);
		} catch (RuntimeException e) {
			logger.error("查询指定HQL异常，HQL：" + hql, e);
			throw e;
		}
	}

	/**
	 * 描述 通过 hql语句 ，参数值 查询实体集合分页方法
	 * @param hql
	 * @param firstResult
	 * @param length
	 * @param objects
	 * @return
	 */
	@SuppressWarnings({ "unchecked" })
//	@Transactional(propagation = Propagation.REQUIRED, readOnly = true)
	public List<T> findPaginationListByHql(final String hql,
			final int firstResult, final int length, final Object... objects) {// TODO

		List<T> result = new ArrayList<T>();
		try {
			result = getHibernateTemplate().executeFind(
					new HibernateCallback<T>() {
						@Override
						public T doInHibernate(Session session)
								throws HibernateException, SQLException {
							Query query = session.createQuery(hql);
							if (objects != null) {
								for (int i = 0; i < objects.length; i++) {
									query.setParameter(i, objects[i]);
								}
							}
							return (T) query.setFirstResult(firstResult)
									.setMaxResults(length).list();
						}
					});
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * 模糊查询列表信息
	 * 
	 * @param tableName
	 * @param names
	 * @param values
	 * @param flag
	 * @return List<?>
	 */
	@SuppressWarnings("rawtypes")
//	@Transactional(propagation = Propagation.REQUIRED, readOnly = true)
	public List<?> QueryFuzzyForList(final String tableName,
			final String[] names, final String[] values, final String[] flag) {// TODO
																				// Auto-generated
		List<?> result = new ArrayList();
		try {
			result = this.getHibernateTemplate().executeFind(
					new HibernateCallback() {
						public Object doInHibernate(Session session)
								throws HibernateException, SQLException {
							String hql = "from " + tableName
									+ " where 1<>0 and ";
							for (int j = 0; j < names.length; j++) {
								hql += names[j] + " like :" + names[j]
										+ flag[j];
							}
							Query q = session.createQuery(hql);
							for (int i = 0; i < values.length; i++) {
								q.setString(names[i], "%" + values[i] + "%");
							}

							return q.list();
						}
					});
		} catch (RuntimeException e) {
			logger.error("模糊查询指定", e);
			throw e;
		}
		return result;
	}

	/**
	 * 模糊查询列表信息 分页
	 * 
	 * @param tableName
	 * @param names
	 * @param values
	 * @param flag
	 *            (" and "," or ")不够的用 "" 补齐
	 * @param firstResult
	 * @param maxResults
	 * @return List<?>
	 */
	@SuppressWarnings("rawtypes")
//	@Transactional(propagation = Propagation.REQUIRED, readOnly = true)
	public List<?> QueryFuzzyForPaginationList(final String tableName,
			final String[] names, final String[] values, final String[] flag,
			final int firstResult, final int maxResults) {// TODO Auto-generated
															// method stub

		List mavinList = new ArrayList();
		try {
			mavinList = this.getHibernateTemplate().executeFind(
					new HibernateCallback() {
						public Object doInHibernate(Session session)
								throws HibernateException, SQLException {
							String hql = "from " + tableName
									+ " where 1<>0 and  ";
							for (int j = 0; j < names.length; j++) {
								hql += names[j] + " like:" + names[j] + flag[j];
							}
							Query q = session.createQuery(hql);

							for (int i = 0; i < values.length; i++) {
								q.setString(names[i], "%" + values[i] + "%");
							}

							q.setFirstResult(firstResult).setMaxResults(
									maxResults);
							return q.list();
						}
					});
		} catch (RuntimeException e) {
			logger.error("模糊查询指定", e);
			throw e;
		}
		return mavinList;
	}

	/**
	 * 描述 按照HQL语句查询唯一对象
	 * 
	 * @param hql
	 * @param values
	 * @return OBJECT对象
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
//	@Transactional(propagation = Propagation.REQUIRED, readOnly = true)
	public Object findUnique(final String hql, final Object... values) {// TODO
		try {
			if (logger.isDebugEnabled()) {
				logger.debug("开始查询返回唯一结果的HQL语句," + hql);
			}
			return getHibernateTemplate().execute(new HibernateCallback() {
				public Object doInHibernate(Session s)
						throws HibernateException, SQLException {
					Query query = createQuery(s, hql, values);

					return query.uniqueResult();
				}
			});
		} catch (RuntimeException e) {
			logger.error("查询指定HQL异常，HQL：" + hql, e);
			throw e;
		}
	}

	/**
	 * 描述 查找指定HQL并返回INT型 只能用于查询对象，不能用于查询某些特定指定结果集值
	 * 
	 * @param hql
	 * @param values
	 * @return int
	 */
	@Override
//	@Transactional(propagation = Propagation.REQUIRED, readOnly = true)
	public int findInt(String hql, Object... values) {// TODO Auto-generated
		return this.findListByHql(hql, values).size();
	}

	/**
	 * 描述 获取指定实体Class指定条件的记录总数
	 * 
	 * @param entityClass
	 * @param where
	 * @param values
	 * @return int
	 */
	@Override
//	@Transactional(propagation = Propagation.REQUIRED, readOnly = true)
	public int findTotalCount(Class<T> entityClass, String where,
			Object... values) {// TODO Auto-generated method stub
		String hql = "select count(e) from " + entityClass.getName() + " as e "
				+ where;
		return findInt(hql, values);
	}

	/**
	 * 描述 获取指定实体Class的记录总数
	 * 
	 * @param entityClass
	 * @return int
	 */
	@Override
//	@Transactional(propagation = Propagation.REQUIRED, readOnly = true)
	public int findTotalCount(Class<T> entityClass) {// TODO Auto-generated
		return findTotalCount(entityClass, "");
	}

	/**
	 * 描述 根据查询条件与参数列表创建Query对象
	 * 
	 * @param session
	 * @param hql
	 * @param objects
	 * @return Query 对象
	 */
	@Override
//	@Transactional(propagation = Propagation.REQUIRED, readOnly = true)
	public Query createQuery(Session session, String hql, Object... objects) {// TODO
		Query query = session.createQuery(hql);
		if (objects != null) {
			for (int i = 0; i < objects.length; i++) {
				query.setParameter(i, objects[i]);
			}
		}
		return query;
	}

	/*
	 * ------------------------------------------------------------------
	 * ------------------------------------------------------------------
	 * -------------------------华丽的分割线---------------------------
	 * ------------------------------------------------------------------
	 * ------------------------------------------------------------------
	 */

	/**
	 * 描述 保存指定实体类 主键ID值不手动设置
	 * 
	 * @param entity
	 */
	@Override
//	@Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class)
	public void save(T entity) {// TODO Auto-generated method stub
		try {
			getHibernateTemplate().save(entity);
			if (logger.isDebugEnabled()) {
				logger.debug("保存实体类成功," + entity.getClass().getName());
			}
		} catch (RuntimeException e) {
			logger.error("保存实体异常," + entity.getClass().getName(), e);
			throw e;
		}
	}

	/**
	 * 描述 保存或更新指定实体类
	 * 
	 * @param t
	 */
	@Override
//	@Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class)
	public void saveOrUpdate(T entity) {// TODO Auto-generated method stub
		try {
			getHibernateTemplate().saveOrUpdate(entity);
			if (logger.isDebugEnabled()) {
				logger.debug("更新或者保存实体成功," + entity.getClass().getName());
			}
		} catch (RuntimeException e) {
			logger.error("更新或保存实体异常", e);
			throw e;
		}
	}

	/**
	 * 描述 删除指定的实体类
	 * 
	 * @param t
	 */
	@Override
//	@Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class)
	public void deleteObject(T entity) {// TODO Auto-generated method stub
		try {
			getHibernateTemplate().delete(entity);
			if (logger.isDebugEnabled()) {
				logger.debug("删除实体类成功," + entity.getClass().getName());
			}
		} catch (RuntimeException e) {
			logger.error("删除实体异常", e);
			throw e;
		}
	}

	/**
	 * 描述 通过 主键id 删除指定的实体类
	 * 
	 * @param id
	 */
	@Override
//	@Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class)
	public void deleteObjectById(Class<T> entityClass, Serializable id) {// TODO
		try {
			this.getHibernateTemplate().delete(this.findById(entityClass, id));
			if (logger.isDebugEnabled()) {
				logger.debug("删除实体类成功," + entityClass.getName());
			}
		} catch (RuntimeException e) {
			logger.error("删除实体异常", e);
			throw e;
		}
	}

	
}
